import sys
import json
from datetime import datetime, timedelta
from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,
                             QListWidget, QListWidgetItem, QLabel, QPushButton, QDialog,
                             QLineEdit, QTextEdit, QComboBox, QMessageBox, QMenu, QProgressBar,
                             QInputDialog, QAction, QFrame, QSizePolicy, QShortcut, QGridLayout,
                             QScrollArea, QSizeGrip, QGraphicsDropShadowEffect)
from PyQt5.QtCore import Qt, QTimer, pyqtSignal, QDateTime, QSize, QPoint
from PyQt5.QtGui import QFont, QColor, QPalette, QKeySequence, QLinearGradient, QBrush

SAVE_FILE = "card_data.json"

class Card:
    def __init__(self, title, answer, tag, proficiency=50, last_practiced=None):
        self.title = title
        self.answer = answer
        self.tag = tag
        self.proficiency = proficiency
        self.last_practiced = last_practiced or datetime.now()
        
    def update_proficiency(self, delta):
        self.proficiency = max(0, min(100, self.proficiency + delta))
        self.last_practiced = datetime.now()
        
    def decay_proficiency(self):
        if self.proficiency >= 100:
            return
        time_since = datetime.now() - self.last_practiced
        if time_since > timedelta(hours=6):
            decay = (time_since // timedelta(hours=6)) * 20
            self.proficiency = max(0, self.proficiency - decay)
            self.last_practiced = datetime.now()

    def to_dict(self):
        return {
            'title': self.title,
            'answer': self.answer,
            'tag': self.tag,
            'proficiency': self.proficiency,
            'last_practiced': self.last_practiced.isoformat()
        }
    
    @classmethod
    def from_dict(cls, data):
        return cls(
            data['title'],
            data['answer'],
            data['tag'],
            data['proficiency'],
            datetime.fromisoformat(data['last_practiced'])
        )

class CardWidget(QWidget):
    rightClicked = pyqtSignal()
    MAX_WIDTH = 400
    MIN_WIDTH = 280
    ASPECT_RATIO = 0.6  # 高度/宽度比例
    
    def __init__(self, card, parent=None):
        super().__init__(parent)
        self.card = card
        self.initUI()
        self.setupShadow()
        
    def initUI(self):
        self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
        self.setMinimumSize(self.MIN_WIDTH, int(self.MIN_WIDTH * self.ASPECT_RATIO))
        self.setMaximumSize(self.MAX_WIDTH, int(self.MAX_WIDTH * self.ASPECT_RATIO))
        
        layout = QVBoxLayout()
        layout.setContentsMargins(15, 15, 15, 15)
        
        title = QLabel(self.card.title)
        title.setFont(QFont("Segoe UI", 14, QFont.Bold))
        title.setAlignment(Qt.AlignCenter)
        title.setStyleSheet("color: #2c3e50; margin-bottom: 12px;")
        title.setWordWrap(True)
        
        progress = QProgressBar()
        progress.setValue(self.card.proficiency)
        progress.setTextVisible(False)
        progress.setFixedHeight(10)
        progress.setStyleSheet("""
            QProgressBar {
                background: rgba(0,0,0,0.1);
                border-radius: 5px;
            }
            QProgressBar::chunk {
                background: qlineargradient(x1:0, y1:0, x2:1, y2:0,
                    stop:0 #3498db, stop:1 #2980b9);
                border-radius: 5px;
            }
        """)
        
        layout.addWidget(title)
        layout.addWidget(progress)
        self.setLayout(layout)
        
        self.setStyleSheet("""
            background: qlineargradient(x1:0, y1:0, x2:1, y2:1,
                stop:0 #ffffff, stop:1 #f8f9fa);
            border-radius: 12px;
            border: 1px solid rgba(0,0,0,0.05);
        """)
        
    def setupShadow(self):
        shadow = QGraphicsDropShadowEffect()
        shadow.setBlurRadius(15)
        shadow.setColor(QColor(0, 0, 0, 30))
        shadow.setOffset(3, 3)
        self.setGraphicsEffect(shadow)
        
    def mousePressEvent(self, event):
        if event.button() == Qt.RightButton:
            self.rightClicked.emit()

class NewCardDialog(QDialog):
    def __init__(self, tags, parent=None):
        super().__init__(parent)
        self.setWindowTitle("新建卡片")
        self.setFixedSize(500, 400)
        self.initUI(tags)
        
    def initUI(self, tags):
        layout = QVBoxLayout()
        layout.setContentsMargins(20, 20, 20, 20)
        
        self.title_input = QLineEdit()
        self.title_input.setPlaceholderText("输入标题...")
        self.title_input.setStyleSheet("""
            QLineEdit {
                font: 14px Segoe UI;
                padding: 10px;
                border: 1px solid #ddd;
                border-radius: 6px;
            }
        """)
        
        self.answer_input = QTextEdit()
        self.answer_input.setPlaceholderText("输入答案...")
        self.answer_input.setStyleSheet("""
            QTextEdit {
                font: 14px Segoe UI;
                padding: 10px;
                border: 1px solid #ddd;
                border-radius: 6px;
                min-height: 100px;
            }
        """)
        
        self.tag_combo = QComboBox()
        self.tag_combo.addItems(tags)
        self.tag_combo.setStyleSheet("""
            QComboBox {
                font: 14px Segoe UI;
                padding: 8px;
                border: 1px solid #ddd;
                border-radius: 6px;
            }
        """)
        
        form = QVBoxLayout(spacing=15)
        form.addWidget(QLabel("标题:"))
        form.addWidget(self.title_input)
        form.addWidget(QLabel("答案:"))
        form.addWidget(self.answer_input)
        form.addWidget(QLabel("标签:"))
        form.addWidget(self.tag_combo)
        
        buttons = QHBoxLayout()
        ok_btn = QPushButton("创建")
        ok_btn.setStyleSheet("""
            QPushButton {
                background: #3498db;
                color: white;
                padding: 12px 25px;
                border-radius: 6px;
                font: bold 14px Segoe UI;
            }
            QPushButton:hover { background: #2980b9; }
        """)
        ok_btn.clicked.connect(self.accept)
        
        cancel_btn = QPushButton("取消")
        cancel_btn.setStyleSheet("""
            QPushButton {
                background: #95a5a6;
                color: white;
                padding: 12px 25px;
                border-radius: 6px;
                font: 14px Segoe UI;
            }
            QPushButton:hover { background: #7f8c8d; }
        """)
        cancel_btn.clicked.connect(self.reject)
        
        buttons.addStretch()
        buttons.addWidget(cancel_btn)
        buttons.addWidget(ok_btn)
        
        layout.addLayout(form)
        layout.addLayout(buttons)
        self.setLayout(layout)

class StudyDialog(QDialog):
    def __init__(self, cards, parent=None):
        super().__init__(parent)
        self.cards = cards
        self.current_index = 0
        self.initUI()
        self.setupShortcuts()
        
    def initUI(self):
        self.setWindowTitle("学习模式")
        self.setMinimumSize(600, 450)
        self.setStyleSheet("background: #f8f9fa;")
        
        main_layout = QVBoxLayout()
        main_layout.setContentsMargins(30, 30, 30, 30)
        
        self.card_frame = QFrame()
        self.card_frame.setStyleSheet("""
            background: white;
            border-radius: 15px;
            padding: 30px;
        """)
        frame_layout = QVBoxLayout()
        
        self.title_label = QLabel()
        self.title_label.setAlignment(Qt.AlignCenter)
        self.title_label.setFont(QFont("Segoe UI", 20, QFont.Bold))
        self.title_label.setStyleSheet("color: #2c3e50; margin-bottom: 20px;")
        
        self.answer_label = QLabel()
        self.answer_label.setAlignment(Qt.AlignCenter)
        self.answer_label.setFont(QFont("Segoe UI", 16))
        self.answer_label.setStyleSheet("color: #7f8c8d; padding: 20px;")
        self.answer_label.hide()
        
        frame_layout.addWidget(self.title_label)
        frame_layout.addWidget(self.answer_label)
        self.card_frame.setLayout(frame_layout)
        
        # 按钮布局
        btn_layout = QHBoxLayout()
        btn_layout.setSpacing(15)
        
        buttons = [
            ("陌生 (1)", "#e74c3c"),
            ("不熟 (2)", "#f1c40f"), 
            ("掌握 (3)", "#2ecc71")
        ]
        
        for text, color in buttons:
            btn = QPushButton(text)
            btn.setFixedHeight(45)
            btn.setFont(QFont("Segoe UI", 12, QFont.Bold))
            darker = self.darker_color(color)
            btn.setStyleSheet(f"""
                QPushButton {{
                    background: {color};
                    color: white;
                    border-radius: 8px;
                }}
                QPushButton:hover {{ background: {self.darker_color(color)}; }}
            """)
            btn.clicked.connect(lambda _, i=buttons.index((text, color))+1: self.handle_answer(i))
            btn_layout.addWidget(btn)
        
        main_layout.addWidget(self.card_frame)
        main_layout.addLayout(btn_layout)
        self.setLayout(main_layout)
        
        self.show_card()
        self.setupShadow()
        
    def darker_color(self, hex_color, factor=0.8):
        color = QColor(hex_color)
        return color.darker(int(factor * 100)).name()
        
    def setupShadow(self):
        shadow = QGraphicsDropShadowEffect()
        shadow.setBlurRadius(20)
        shadow.setColor(QColor(0,0,0,30))
        shadow.setOffset(5,5)
        self.card_frame.setGraphicsEffect(shadow)
        
    def setupShortcuts(self):
        QShortcut(QKeySequence("1"), self).activated.connect(lambda: self.handle_answer(1))
        QShortcut(QKeySequence("2"), self).activated.connect(lambda: self.handle_answer(2))
        QShortcut(QKeySequence("3"), self).activated.connect(lambda: self.handle_answer(3))
        QShortcut(Qt.Key_Space, self).activated.connect(self.toggle_answer)
        QShortcut(Qt.Key_Q, self).activated.connect(self.prev_card)
        QShortcut(Qt.Key_E, self).activated.connect(self.next_card)
        
    def toggle_answer(self):
        self.answer_label.setVisible(not self.answer_label.isVisible())
        if self.answer_label.isVisible():
            self.title_label.setAlignment(Qt.AlignTop)
            self.title_label.setStyleSheet("color: #2c3e50; margin-bottom: 10px;")
        else:
            self.title_label.setAlignment(Qt.AlignCenter)
            self.title_label.setStyleSheet("color: #2c3e50; margin-bottom: 20px;")
            
    def show_card(self):
        card = self.cards[self.current_index]
        self.title_label.setText(card.title)
        self.answer_label.setText(card.answer)
        self.answer_label.hide()
        
    def prev_card(self):
        self.current_index = max(0, self.current_index - 1)
        self.show_card()
        
    def next_card(self):
        self.current_index = min(len(self.cards)-1, self.current_index + 1)
        self.show_card()
        
    def handle_answer(self, level):
        card = self.cards[self.current_index]
        if level == 1:
            card.update_proficiency(-20)
        elif level == 3:
            card.update_proficiency(20)
        
        if self.current_index == len(self.cards) - 1:
            self.accept()
        else:
            self.next_card()

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.cards = []
        self.tags = []
        self.initUI()
        self.load_data()
        
    def initUI(self):
        self.setWindowTitle("记忆卡片")
        self.setGeometry(100, 100, 1200, 800)
        self.setStyleSheet("""
            background: #f8f9fa;
            font-family: Segoe UI;
        """)
        
        # 初始化菜单栏
        self.setupMenu()
        # 初始化快捷键
        self.setupShortcuts()
        # 初始化主界面
        self.setupMainUI()
        
    def setupMenu(self):
        menubar = self.menuBar()
        file_menu = menubar.addMenu("文件")
        
        actions = [
            ("新建文件夹 (N)", "Ctrl+N", self.create_folder),
            ("新建卡片 (A)", "Ctrl+A", self.create_card),
            ("学习模式 (S)", "Ctrl+S", self.start_study),
            ("保存数据", "Ctrl+W", self.save_data),
            ("退出", "Ctrl+Q", self.close)
        ]
        
        for text, shortcut, handler in actions:
            action = QAction(text, self)
            action.setShortcut(QKeySequence(shortcut))
            action.triggered.connect(handler)
            file_menu.addAction(action)
            
    def setupShortcuts(self):
        QShortcut(QKeySequence("h"), self).activated.connect(self.show_help)
        QShortcut(QKeySequence("o"), self).activated.connect(self.show_settings)
        
    def setupMainUI(self):
        main_widget = QWidget()
        self.setCentralWidget(main_widget)
        layout = QHBoxLayout()
        layout.setContentsMargins(20, 20, 20, 20)
        layout.setSpacing(20)
        
        # 左侧标签列表
        self.tag_list = QListWidget()
        self.tag_list.setFixedWidth(280)
        self.tag_list.setFont(QFont("Segoe UI", 12))
        self.tag_list.setStyleSheet("""
            QListWidget {
                background: white;
                border-radius: 10px;
                padding: 10px;
                border: 1px solid rgba(0,0,0,0.05);
            }
            QListWidget::item {
                padding: 15px;
                border-radius: 8px;
                margin: 5px 0;
            }
            QListWidget::item:selected {
                background: #3498db;
                color: white;
            }
        """)
        self.tag_list.itemClicked.connect(self.show_tag_cards)
        layout.addWidget(self.tag_list)
        
        # 右侧卡片区域
        scroll = QScrollArea()
        scroll.setWidgetResizable(True)
        scroll.setStyleSheet("border: none; background: transparent;")
        
        self.card_container = QWidget()
        self.card_layout = QGridLayout()
        self.card_layout.setAlignment(Qt.AlignTop)
        self.card_layout.setHorizontalSpacing(20)
        self.card_layout.setVerticalSpacing(25)
        self.card_container.setLayout(self.card_layout)
        
        scroll.setWidget(self.card_container)
        layout.addWidget(scroll)
        
        main_widget.setLayout(layout)
        
    def resizeEvent(self, event):
        self.adjustCardLayout()
        super().resizeEvent(event)
        
    def adjustCardLayout(self):
        container_width = self.card_container.width() - 40  # 减去滚动条和边距
        min_card_width = CardWidget.MIN_WIDTH
        max_card_width = CardWidget.MAX_WIDTH
        
        # 计算可用列数
        available_width = container_width - self.card_layout.horizontalSpacing() * 2
        columns = max(1, available_width // (min_card_width + self.card_layout.horizontalSpacing()))
        column_width = min(
            max_card_width, 
            (available_width - self.card_layout.horizontalSpacing() * (columns - 1)) // columns
        )
        
        # 更新所有卡片尺寸
        for i in range(self.card_layout.count()):
            item = self.card_layout.itemAt(i)
            if widget := item.widget():
                widget.setFixedWidth(column_width)
                widget.setFixedHeight(int(column_width * CardWidget.ASPECT_RATIO))
        
    def show_help(self):
        help_text = """快捷键指南：
        Ctrl+N - 新建文件夹
        Ctrl+A - 新建卡片
        Ctrl+S - 开始学习
        Ctrl+W - 保存数据
        Ctrl+Q - 退出程序
        H - 显示帮助
        O - 打开设置
        
        学习模式快捷键：
        Q - 上一个卡片
        E - 下一个卡片
        空格 - 显示答案
        1/2/3 - 选择熟练度"""
        QMessageBox.information(self, "帮助", help_text)
        
    def show_settings(self):
        QMessageBox.information(self, "设置", "设置功能开发中，敬请期待...")
        
    def create_folder(self):
        tag, ok = QInputDialog.getText(self, "新建文件夹", "输入新标签名称:")
        if ok and tag:
            if tag not in self.tags:
                self.tags.append(tag)
                self.update_tag_list()
                self.save_data()
                
    def update_tag_list(self):
        self.tag_list.clear()
        for tag in self.tags:
            item = QListWidgetItem(tag)
            item.setFont(QFont("Segoe UI", 12))
            self.tag_list.addItem(item)
            
    def create_card(self):
        if not self.tags:
            QMessageBox.warning(self, "错误", "请先创建至少一个标签文件夹")
            return
            
        dialog = NewCardDialog(self.tags, self)
        if dialog.exec_():
            title = dialog.title_input.text().strip()
            answer = dialog.answer_input.toPlainText().strip()
            tag = dialog.tag_combo.currentText()
            
            if not title or not answer:
                QMessageBox.warning(self, "输入错误", "标题和答案不能为空")
                return
                
            new_card = Card(title, answer, tag)
            self.cards.append(new_card)
            self.show_tag_cards()
            self.save_data()
            
    def show_tag_cards(self):
        # 清空现有布局
        while self.card_layout.count():
            item = self.card_layout.takeAt(0)
            if widget := item.widget():
                widget.deleteLater()
                
        if not self.tag_list.selectedItems():
            return
            
        current_tag = self.tag_list.currentItem().text()
        filtered = [c for c in self.cards if c.tag == current_tag]
        
        row = col = 0
        max_columns = self.calculate_max_columns()
        
        for card in filtered:
            card_widget = CardWidget(card)
            card_widget.rightClicked.connect(lambda _, c=card: self.show_card_info(c))
            self.card_layout.addWidget(card_widget, row, col)
            
            col += 1
            if col >= max_columns:
                col = 0
                row += 1
        
        self.adjustCardLayout()
                
    def calculate_max_columns(self):
        container_width = self.card_container.width() - 40
        min_card_width = CardWidget.MIN_WIDTH
        return max(1, container_width // (min_card_width + self.card_layout.horizontalSpacing()))
        
    def show_card_info(self, card):
        info = f"""📚 卡片详情：
        
• 标题：{card.title}
• 标签：{card.tag}
• 熟练度：{card.proficiency}%
• 最后练习：{card.last_practiced.strftime('%Y-%m-%d %H:%M')}

提示：熟练度达到100%的卡片将暂停复习3天"""
        msg = QMessageBox()
        msg.setWindowTitle("卡片详情")
        msg.setText(info)
        msg.setStyleSheet("""
            QMessageBox {
                font: 14px Segoe UI;
                background: white;
            }
            QLabel { min-width: 400px; }
        """)
        msg.exec_()
        
    def start_study(self):
        if not self.tag_list.selectedItems():
            QMessageBox.warning(self, "错误", "请先选择要学习的标签")
            return
            
        current_tag = self.tag_list.currentItem().text()
        filtered = [c for c in self.cards if c.tag == current_tag]
        if not filtered:
            QMessageBox.warning(self, "提示", "该标签下还没有任何卡片")
            return
            
        filtered.sort(key=lambda x: x.proficiency)
        for card in filtered:
            card.decay_proficiency()
            
        dialog = StudyDialog(filtered, self)
        dialog.exec_()
        self.show_tag_cards()
        self.save_data()
        
    def save_data(self):
        data = {
            'tags': self.tags,
            'cards': [c.to_dict() for c in self.cards]
        }
        try:
            with open(SAVE_FILE, 'w', encoding='utf-8') as f:
                json.dump(data, f, ensure_ascii=False, indent=2)
        except Exception as e:
            QMessageBox.critical(self, "保存失败", f"数据保存失败：{str(e)}")
            
    def load_data(self):
        try:
            with open(SAVE_FILE, 'r', encoding='utf-8') as f:
                data = json.load(f)
                self.tags = data['tags']
                self.cards = [Card.from_dict(c) for c in data['cards']]
                self.update_tag_list()
        except FileNotFoundError:
            pass
        except Exception as e:
            QMessageBox.warning(self, "加载错误", f"数据加载失败：{str(e)}")
            
    def closeEvent(self, event):
        self.save_data()
        event.accept()

if __name__ == "__main__":
    app = QApplication(sys.argv)
    app.setStyle("Fusion")
    
    # 设置全局配色
    palette = QPalette()
    palette.setColor(QPalette.Window, QColor(248, 249, 250))
    palette.setColor(QPalette.Base, QColor(255, 255, 255))
    palette.setColor(QPalette.Button, QColor(240, 240, 240))
    app.setPalette(palette)
    
    font = QFont("Segoe UI", 12)
    app.setFont(font)
    
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())